package idv.takeshi.software.productline.bookstore.domain.model.book;

import java.math.BigDecimal;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Entity;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

/**
 * A model class which is one kind of promotion, discount.
 * @author takeshi
 *
 */
@Entity
public class Discount extends Promotion {
	
	@Column
	private BigDecimal discount = new BigDecimal("1.0");

	/**
	 * @return the discount
	 */
	public BigDecimal getDiscount() {
		return discount;
	}

	/**
	 * Set discount.
	 * Here are two check rules before setting the discount<br>
	 * <ol>
	 * 	<li>discount shall not small than 0</li>
	 * 	<li>discount shall not greater than 1.0</li>
	 * </ol>
	 * @param discount the discount to set
	 * @throws DiscountSettingException if above check rules violated.
	 */
	public void setDiscount(BigDecimal discount) throws DiscountSettingException {
		Validate.notNull(discount, "discount shall always not be null");
		if(discount.compareTo(new BigDecimal("0")) < 0){
			throw new DiscountSmallThanZeroException("discount:" + discount +
					" shall greater than or euqlas to 0");
		}
		if(discount.compareTo(new BigDecimal("1.0")) > 0){
			throw new DiscountGreaterThanOneException("discount:" + discount +
					" shall small than or equals to 1.0");
		}
		this.discount = discount;
	}

	/**
	 * Calculate a promoted price by discount algorithm.
	 * @param book
	 * @return calculated price
	 */
	@Override
	public BigDecimal getPromotedPrice(Book book) {
		BigDecimal fixedPrice = getFixedPrice(book);
		return fixedPrice.multiply(discount);
	}

	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.domain.model.book.Promotion#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj == null) { return false; }
		   if (obj == this) { return true; }
		   if (obj.getClass() != getClass()) {
		     return false;
		   }
		   Discount rhs = (Discount) obj;
		   return new EqualsBuilder()
		   	   .appendSuper(super.equals(rhs))
			   .append(this.discount, rhs.discount)
		       .isEquals();
	}

	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.domain.model.book.Promotion#hashCode()
	 */
	@Override
	public int hashCode() {
		return new HashCodeBuilder(43, 47).
		   appendSuper(super.hashCode()).
	       append(this.discount).
	       toHashCode();
	}
 
}
 
